package org.imagiccode.core.base;

import com.alibaba.dubbo.common.utils.Assert;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.web.util.WebUtils;
import org.imagiccode.core.Constants;
import org.imagiccode.core.util.DataUtil;
import org.imagiccode.core.util.InstanceUtil;
import org.imagiccode.core.util.RedisUtil;
import org.imagiccode.core.util.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

import io.swagger.models.auth.In;


/**
 * 服务基类
 *
 * @author 1340760685@qq.com
 * @create 2016-12-05 20:16
 **/
public class BaseService<T extends BaseModel> {
    protected Logger logger = LogManager.getLogger();
    @Autowired
    BaseMapper<T> mapper;

    /**
     * 启动分页查询
     */
    protected void startPage(Map<String, Object> params) {
        if (DataUtil.isEmpty(params.get("pageNum"))) {
            params.put("pageNum", 1);
        }
        if (DataUtil.isEmpty(params.get("pageSize"))) {
            params.put("pageSize", 10);
        }
        if (DataUtil.isEmpty(params.get("orderBy"))) {
            params.put("orderBy", "id_ desc");
        }
        PageHelper.startPage(params);
    }

    private BaseService<T> getProvider() {
        return InstanceUtil.getBean(getClass());
    }

    public PageInfo<T> getPage(Page<Integer> ids) {
        if (ids != null) {
            Page<T> page = new Page(ids.getPageNum(), ids.getPageSize());
            page.setTotal(ids.getTotal());
            page.clear();
            BaseService<T> provider = getProvider();
            for (Integer id : ids) {
                page.add(provider.queryById(id));
            }
            return new PageInfo<>(page);
        }
        return new PageInfo<>();
    }

    public List<T> getList(List<Integer> ids) {
        List<T> list = InstanceUtil.newArrayList();
        if (ids != null) {
            for (Integer id : ids) {
                list.add(getProvider().queryById(id));
            }
        }
        return list;
    }
    /** 根据Id查询(cls返回类型Class) */
    public <K> List<K> getList(List<Integer> ids, Class<K> cls) {
        List<K> list = InstanceUtil.newArrayList();
        if (ids != null) {
            for (Integer id : ids) {
                T t = getProvider().queryById(id);
                K k = InstanceUtil.to(t, cls);
                list.add(k);
            }
        }
        return list;
    }

    @Transactional
    public T queryById(Integer id) {
        try {
            String key = getCacheKey(id);
            T record = (T) RedisUtil.get(key);
            if (record == null) {
                record = mapper.selectByPrimaryKey(id);
                RedisUtil.set(key, record);
            }
            return record;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }

    }
    @Transactional
    public void delete(Integer id){
        try{
            T record=queryById(id);
            record.setEnable(false);
            record.setUpdateTime(new Date());
            mapper.updateByPrimaryKey(record);
            RedisUtil.set(getCacheKey(id),record);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    @Transactional
    public T add(T record){
        try{
            record.setEnable(true);
            record.setUpdateTime(new Date());
            record.setCreateTime(new Date());
            record.setCreateBy(WebUtil.getCurrentUser());
            mapper.insert(record);
            RedisUtil.set(getCacheKey(record.getId()),record);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
        return record;
    }
    @Transactional
    public T update(T record){
        Assert.notNull(record.getId(),"ID");
        try{
            record.setEnable(true);
            record.setUpdateTime(new Date());
            record.setUpdateBy(WebUtil.getCurrentUser());
            mapper.updateByPrimaryKey(record);
            RedisUtil.set(getCacheKey(record.getId()),record);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
        return record;
    }
    private String getCacheKey(Object id) {
        String cacheName = null;
        CacheConfig cacheConfig = getClass().getAnnotation(CacheConfig.class);
        if (cacheConfig == null || cacheConfig.cacheNames() == null || cacheConfig.cacheNames().length < 1) {
            cacheName = getClass().getName();
        } else {
            cacheName = cacheConfig.cacheNames()[0];
        }
        return new StringBuilder(Constants.CACHE_NAMESPACE).append(cacheName).append(":").append(id).toString();
    }
}
